package com.itheima.a04;

import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import org.springframework.beans.factory.annotation.InjectionMetadata;
import org.springframework.beans.factory.config.DependencyDescriptor;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.ContextAnnotationAutowireCandidateResolver;
import org.springframework.core.MethodParameter;
import org.springframework.core.env.StandardEnvironment;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * @author: AirMan
 * @date: 2025/4/9 15:23
 * @description: MyDigInAutowired
 */
public class MyDigInAutowired {
    public static void main(String[] args) throws Throwable {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        beanFactory.registerSingleton("bean2", new Bean2());
        beanFactory.registerSingleton("bean3", new Bean3());
        beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver()); // @Value
        beanFactory.addEmbeddedValueResolver(new StandardEnvironment()::resolvePlaceholders);

        Bean1 bean1 = new Bean1();
        System.out.println(bean1);

        // 1. 查找哪些属性、方法加了 @Autowired, 这称之为 InjectionMetadata
        AutowiredAnnotationBeanPostProcessor processor =
                new AutowiredAnnotationBeanPostProcessor();
        processor.setBeanFactory(beanFactory);

        // 执行依赖注入 @Autowired @Value
//        processor.postProcessProperties(null, bean1, "bean1");

//        Class<?> clazz = Class.forName("org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor");
//        Method method =
//                clazz.getDeclaredMethod("findAutowiringMetadata", String.class, Class.class, PropertyValues.class);
//
//        method.setAccessible(true);
//        InjectionMetadata metadata = (InjectionMetadata) method.invoke(processor,"bean1", bean1.getClass(), null);
//        metadata.inject(bean1, "bean1", null);
//        System.out.println(bean1);


        Field bean3 = Bean1.class.getDeclaredField("bean3");
        DependencyDescriptor dd1 = new DependencyDescriptor(bean3, false);
        Object o1 = beanFactory.doResolveDependency(dd1, null, null, null);
        System.out.println(o1);

        Method setBean2 = Bean1.class.getDeclaredMethod("setBean2", Bean2.class);
        DependencyDescriptor dd2 = new DependencyDescriptor(new MethodParameter(setBean2, 0), true);
        Object o2 = beanFactory.doResolveDependency(dd2, null, null, null);
        System.out.println(o2);


    }
}
